# -*- coding: utf-8 -*-

import sip
sip.setapi('QString', 2)
sip.setapi('QStringList', 2)
sip.setapi('QVariant', 2)

from QueryStatus import QueryStatus
from PyQt4 import QtCore

#_______________________________________________________________________________
class ServerModel(QtCore.QObject):
    def __init__(self):
        QtCore.QObject.__init__(self)
        self.info_connection = {"host": "localhost", "port": 6600, 
                                "connected": False}
        self.info_song = {}
        self.info_status = {}
        self.info_playlist = {}
    
    def connect(self, cur_status, cur_song):
        self.info_connection["connected"] = True
        self.update_statusInfo(cur_status)
        self.update_playlistInfo(cur_status)
        self.update_songInfo(cur_song)
    
    def disconnect(self):
        self.info_connection["connected"] = False
      
    def update_playlistInfo(self, cur_playlist, pl_changes=[]):
        if self.info_playlist:
            pl_len = self.info_playlist["playlistlength"] 
        else:
            pl_len = 0
        if self.info_status:
            self.info_playlist = {}
            self.info_playlist["track_list"] = {}
            for song in cur_playlist:
                self.info_playlist["track_list"][song["id"]] = song
            self.info_playlist["playlistlength"] = self.info_status["playlistlength"]
            self.info_playlist["len_diff"] = int(pl_len) - \
                                        int(self.info_status["playlistlength"])
            self.info_playlist["changes"] = pl_changes
        
    def update_statusInfo(self, cur_status):
        if self.info_status:
            muted = self.info_status["volume"]["muted"]
            value = self.info_status["volume"]["value"]
        else:
            muted = False
            value = 0 
        self.info_status = {}
        for k, v in cur_status.iteritems():
            if k == "volume":
                if muted is False:
                    v = {"value": int(v), "muted": muted}
                else:
                    v = {"value": value, "muted": muted} 
            elif k == "time":
                v = int(v.split(":")[0])
            elif k == "random" or k == "single" or k == "repeat" or k == "consume":
                v = int(v)
            elif k == "playlistlength":
                v = int(v)
            self.info_status[k] = v 

    def update_songInfo(self, cur_song):
        self.info_song = {}
        if cur_song:
            for k, v in cur_song.iteritems():
                if k == "id":
                    v = int(v)
                elif k == "track":
                    v = int(v.split("/")[0])
                elif k == "date":
                    v = int(v.split("-")[0])
                elif k == "time":
                    v = int(v)
                self.info_song[k] = v

#_______________________________________________________________________________
class ServerController(QtCore.QObject):
    """FIXME: sistemare i segnali, la logica di comunicazione"""
    client_connected = QtCore.pyqtSignal(bool)
    playlist_changed = QtCore.pyqtSignal()
    database_updated = QtCore.pyqtSignal()
    player_started = QtCore.pyqtSignal()
    player_stopped = QtCore.pyqtSignal()
    player_paused = QtCore.pyqtSignal()
    player_song_changed = QtCore.pyqtSignal()
    player_song_seeked = QtCore.pyqtSignal()
    mixer_volume_changed = QtCore.pyqtSignal()
    options_changed = QtCore.pyqtSignal(str)
    
    def __init__(self, client):
        QtCore.QObject.__init__(self)
        self.model = ServerModel()
        self.client = client
        self.querying = False
    
    def send_notification(self, subsystem_list):
        cur_info_status = self.client.status()
        cur_info_song = self.client.currentsong()
        cur_info_playlist = self.client.playlistinfo()
        for subsystem in subsystem_list:
            if subsystem == "database":
                self.model.update_statusInfo(cur_info_status)
                self.model.update_songInfo(cur_info_song)
                self.database_updated.emit()
            elif subsystem == "update":
                self.model.update_statusInfo(cur_info_status)
            elif subsystem == "stored_playlist":
                self.model.update_statusInfo(cur_info_status)
            elif subsystem == "playlist":
#                if self.model.info_status:
#                    changes = self.client.plchangesposid(self.model.info_status["playlist"])
#                else:
#                    changes = []
                self.model.update_statusInfo(cur_info_status)
#                self.model.update_songInfo(cur_info_song)
#                self.model.update_playlistInfo(cur_info_playlist, changes)
                self.playlist_changed.emit()
            elif subsystem == "player":
                saved_info_status = self.model.info_status
                if cur_info_status["state"] != saved_info_status["state"]:
                    """state changed"""
                    self.model.update_statusInfo(cur_info_status)
                    self.model.update_songInfo(cur_info_song)
                    if self.model.info_status["state"] == "play":
                        self.player_started.emit()
                    elif self.model.info_status["state"] == "pause":
                        self.player_paused.emit()
                    else:
                        self.player_stopped.emit()
                else:
                    saved_info_song = self.model.info_song
                    if int(cur_info_song["id"]) != saved_info_song["id"]:
                        """song changed"""
                        self.model.update_statusInfo(cur_info_status)
                        self.model.update_songInfo(cur_info_song)
                        self.player_song_changed.emit()
                    else:
                        """song seeked"""
                        self.model.update_statusInfo(cur_info_status)
                        self.player_song_seeked.emit()
            elif subsystem == "mixer":
                """volume changed"""
                self.model.update_statusInfo(cur_info_status)
                self.mixer_volume_changed.emit()
            elif subsystem == "output":
                self.model.update_statusInfo(cur_info_status)
            elif subsystem == "options":
                if self.model.info_status["random"] != int(cur_info_status["random"]):
                    msg = "random"
                    self.model.update_statusInfo(cur_info_status)
                    self.options_changed.emit(msg)
                elif self.model.info_status["repeat"] != int(cur_info_status["repeat"]):
                    if int(cur_info_status["repeat"]):
                        if not self.model.info_status["single"]:
                            msg = "repeat_pl"
                            self.model.update_statusInfo(cur_info_status)
                            self.options_changed.emit(msg)                            
                        else:
                            msg = "repeat_song"
                            self.model.update_statusInfo(cur_info_status)
                            self.options_changed.emit(msg)                            
                    else:
                        if not self.model.info_status["single"]:
                            msg = "repeat_norm"
                            self.model.update_statusInfo(cur_info_status)
                            self.options_changed.emit(msg)                            
                        else:
                            msg = "stop_after" 
                            self.model.update_statusInfo(cur_info_status)
                            self.options_changed.emit(msg)                            
                elif self.model.info_status["single"] != int(cur_info_status["single"]):
                    if int(cur_info_status["single"]):
                        if not self.model.info_status["repeat"]:
                            msg = "stop_after"
                            self.model.update_statusInfo(cur_info_status)
                            self.options_changed.emit(msg)                            
                        else:
                            msg = "repeat_song"
                            self.model.update_statusInfo(cur_info_status)
                            self.options_changed.emit(msg)                        
                    else:
                        if not self.model.info_status["repeat"]:
                            msg = "repeat_norm"
                            self.model.update_statusInfo(cur_info_status)
                            self.options_changed.emit(msg)
                        else:
                            msg = "repeat_pl" 
                            self.model.update_statusInfo(cur_info_status)
                            self.options_changed.emit(msg)                       
                elif self.model.info_status["consume"] != int(cur_info_status["consume"]):
                    msg = "consume"
                    self.model.update_statusInfo(cur_info_status)
                    self.options_changed.emit(msg)
                elif self.model.info_status["xfade"] != cur_info_status["xfade"]:
                    msg = "xfade"
                    self.model.update_statusInfo(cur_info_status)
                    self.options_changed.emit(msg)

    def start_querying(self):
        try:
            if self.querying is True:
                return
            self.querying = True
            self.querying_thread.start()
        except Exception, err:
            raise err
    
    def stop_querying(self):
        try:
            if self.querying is False:
                return
            self.querying = False
            self.querying_thread.stop()
            self.querying_thread.wait()
        except Exception, err:
            raise err

    def connect(self):
        try:
            self.client.connect(self.model.info_connection["host"], 
                                self.model.info_connection["port"])
            self.querying_thread = QueryStatus(self.client, self.model.info_connection)
            cur_info_status = self.client.status()
            cur_info_song = self.client.currentsong()
            cur_info_playlist = self.client.playlistinfo() 
            self.model.info_connection["connected"] = True
            self.model.update_statusInfo(cur_info_status)
            self.model.update_playlistInfo(cur_info_playlist)
            self.model.update_songInfo(cur_info_song)
            #Signal
            self.client_connected.emit(True)
            self.playlist_changed.emit()
            self.querying_thread.idle_notified.connect(self.send_notification)
            if self.model.info_status["state"] == "play":
                self.player_started.emit()
            elif self.model.info_status["state"] == "pause":
                self.player_paused.emit()
            #Querying
            self.start_querying()
        except Exception, err:
            raise err

    def disconnect(self):
        try:
            if self.model.info_connection["connected"] == False:    
                return
            if self.querying is True:
                self.querying_thread.idle_notified.disconnect()
                self.stop_querying()
            self.client.close()
            self.client.disconnect()
            self.model.disconnect()
            self.client_connected.emit(False)
        except Exception, err:
            raise err

